package com.qing.demo.netty.web;

import cn.hutool.json.JSONUtil;
import com.qing.demo.netty.domain.EasyResult;
import com.qing.demo.netty.domain.ServerInfo;
import com.qing.demo.netty.domain.UserChannelInfo;
import com.qing.demo.netty.redis.RedisUtil;
import com.qing.demo.netty.server.NettyServer;
import com.qing.demo.netty.service.ExtServerService;
import com.qing.demo.netty.util.CacheUtil;
import com.qing.demo.netty.util.NetUtil;
import io.netty.channel.Channel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author caozhipeng
 * @date 2025/8/7
 */
@Slf4j
@Controller
public class NettyController {

    private static ExecutorService executorService= Executors.newFixedThreadPool(2);

    @Value("${server.port}")
    private int serverPort;

    @Autowired
    private ExtServerService extServerService;


    @Autowired
    private RedisUtil redisUtil;

    private NettyServer nettyServer;

    @RequestMapping("/index")
    public String index(Model model){
        model.addAttribute("serverPort",serverPort);
        return "index";
    }


    @RequestMapping("/openNattyServer")
    @ResponseBody
    public EasyResult openNettyServer(){
        try {
            int port= NetUtil.getPort();
            log.info("启动Netty服务，获取可用端口：{}",port);
            nettyServer=new NettyServer(new InetSocketAddress(port),extServerService);

            Future<Channel> future=executorService.submit(nettyServer);
            Channel channel=future.get();
            if(null==channel){
                log.error("启动Netty服务失败！ e: {}");
            }
            while(!channel.isActive()){
                log.info("启动Netty服务，循环等待启动.....");
                Thread.sleep(500);
            }
            CacheUtil.serverInfoMap.put(port,new ServerInfo(NetUtil.getHost(),port,new Date()));
            CacheUtil.serverMap.put(port,nettyServer);
            log.info("Netty服务启动成功，端口：{}",port);
            return EasyResult.buildSuccessResult();
        }catch (Exception ex){
            log.error("启动Netty服务失败！ e: {}",ex.getMessage());
            return EasyResult.buildErrorResult(ex);
        }
    }


    @RequestMapping("/closeNettyServer")
    @ResponseBody
    public EasyResult closeNettyServer(int port){
        try {
            log.info("关闭Netty服务开始，端口: {}",port);
            NettyServer nettyServer=CacheUtil.serverMap.get(port);
            if(null==nettyServer){
                CacheUtil.serverMap.remove(port);
                return EasyResult.buildSuccessResult();
            }
            nettyServer.destroy();
            CacheUtil.serverMap.remove(port);
            CacheUtil.serverInfoMap.remove(port);
            redisUtil.clear();
            log.info("关闭Netty服务完成！端口：{}",port);
            return EasyResult.buildSuccessResult();
        }catch (Exception ex){
            log.error("关闭Netty服务失败！端口：{}",port,ex.getMessage());
            return EasyResult.buildErrorResult(ex);
        }
    }


    @RequestMapping("/queryNettyServerList")
    @ResponseBody
    public Collection<ServerInfo> queryNettyServerList(){
        try {
            Collection<ServerInfo> serverInfos=CacheUtil.serverInfoMap.values();
            log.info("查询服务端列表。{}", JSONUtil.toJsonStr(serverInfos));
            return serverInfos;
        }catch (Exception ex){
            log.error("查询Netty服务列表失败！",ex.getMessage());
            return null;
        }
    }

    @RequestMapping("/getUserChannelInfoList")
    @ResponseBody
    public List<UserChannelInfo> getUserChannelInfoList(){
        List<UserChannelInfo> list=redisUtil.popList();
        return list;
    }

}
